package com.topisv.tms.service.stock.check;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import net.sf.json.JSONArray;

import org.apache.commons.lang.StringUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.stock.check.CheckCountTask;
import com.topisv.tms.entity.stock.check.CheckFixTask;
import com.topisv.tms.entity.stock.check.CheckPlan;
import com.topisv.tms.entity.stock.check.CheckPlanItem;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.stock.check.CheckCountTaskDao;
import com.topisv.tms.repository.stock.check.CheckFixTaskDao;
import com.topisv.tms.repository.stock.check.CheckPlanDao;
import com.topisv.tms.repository.stock.check.CheckPlanItemDao;
import com.topisv.tms.utils.rule.TMSTransportRule;

@Component
@Transactional(readOnly = true)
public class CheckCountTaskService {

	@Autowired
	private CheckCountTaskDao checkCountTaskDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private CheckPlanDao checkPlanDao;
	@Autowired
	private CheckPlanItemDao checkPlanItemDao;
	@Autowired
	private CheckFixTaskDao checkFixTaskDao;

	/**
	 * 查询任务
	 * @param params
	 * @return
	 */
	public List<CheckCountTask> loadTask(Map<String, Object> params) {
		Sort sort = new Sort(Sort.Direction.DESC,"id");
	    Specification<CheckCountTask> spec =this.getWhereClause(params);
	    List<CheckCountTask> taskList = this.checkCountTaskDao.findAll(spec, sort);
	    for (CheckCountTask task : taskList) {
			this.setDetail(task);
		}
	    return taskList;
	}
	
	/**
	 * 设置属性
	 * @param task
	 */
	private void setDetail(CheckCountTask task){
		
		//customer
		String customerCode=task.getCustomerCode();
		Customers customer=this.customersDao.findByCustomerCode(customerCode);
		task.setCustomer(customer);
		
		//warehouse
		String warehouseCode=task.getWarehouseCode();
		AreaGroup warehouse=this.areaGroupDao.findByGroupCode(warehouseCode);
		task.setWarehouse(warehouse);
		
		//creater
		User user=this.userDao.findByJobuuid(task.getWorkerUuid());
		task.setWorker(user);
		
		//checkPlan
		CheckPlan plan=this.checkPlanDao.loadByPlanCode(task.getPlanCode());
		task.setPlan(plan);
	}
	
	
	/**
	 * 条件封装
	 * @param params
	 * @return
	 */
	private Specification<CheckCountTask> getWhereClause(final Map<String, Object> params) {
		 return new Specification<CheckCountTask>(){
		    @Override
		    public Predicate toPredicate(Root<CheckCountTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      //customerCodes
		      String customerCodes=(String) params.get("customerCodes");
		      if(StringUtils.isNotBlank(customerCodes)){
		    	  String[] customerCodeSplit = customerCodes.split(":");
				  ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodeSplit.length];
				  int i = 0;
				  for (String _customerCode : customerCodeSplit) {
					 tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customerCode);
					 i++;
				  }
				  pre.getExpressions().add(cb.or(tempCustomerCode));
		      }
			  
		      
		      //areagroups
		      String areagroups=(String) params.get("areagroups");
		      if(StringUtils.isNotBlank(areagroups)){
		    	  String[] areagroupSplit = areagroups.split(":");
				  ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
				  int j = 0;
				  for (String _areagroup : areagroupSplit) {
						areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), _areagroup);
						j++;
				  }
				  pre.getExpressions().add(cb.or(areagroupArray)); 
		      }
			  
			  
              //createTime
		      Date fromDate= (Date) params.get("fromDate");
		      if (fromDate != null) {
		        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createTime"), fromDate));
		      }
		      Date toDate= (Date) params.get("toDate");
		      if (toDate != null) {
		        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createTime"), toDate));
		      }
		      
		      //status
		      String status=(String) params.get("status");
		      if(StringUtils.isNotBlank(status)){
		    	  if("myTask".equals(status)){
		    		  pre.getExpressions().add(cb.or(
		    				  cb.equal(r.get("status"),"token"),
		    				  cb.equal(r.get("status"),"doing")
		    		  )); 
		    	  }else{
		    		  pre.getExpressions().add(cb.equal(r.get("status"),status));
		    	  }
			  }
		      
		      //workerUuid
		      String workerUuid=(String) params.get("workerUuid");
		      if(StringUtils.isNotBlank(workerUuid)){
					pre.getExpressions().add(cb.equal(r.get("workerUuid"),workerUuid));
			  }
		      
		      return pre;
		    }
		  };
	}

	/**
	 * 领取点数任务
	 * @param taskId
	 * @param jobuuid
	 */
	@Transactional(readOnly = false)
	public String takeTask(Long taskId, String jobuuid) {
		
		CheckCountTask task=this.checkCountTaskDao.findOne(taskId);
		
		//已经被领取
		if(!"undo".equals(task.getStatus())){
			return "token"; 
		}
		
		//领取
		task.setStatus("token");
		task.setWorkerUuid(jobuuid);
		this.checkCountTaskDao.save(task);
		
		//修改计划状态：领取校对任务
		CheckPlan plan=this.checkPlanDao.loadByPlanCode(task.getPlanCode());
		plan.setStatus("2"); //状态 （1.创建盘点计划 2.领取点数任务 3.点数任务完成 4.领取校对任务 5.校对任务完成）
		this.checkPlanDao.save(plan);
		
		return "success";
	}

	/**
	 * 查询
	 * @param taskId 任务ID
	 * @return
	 */
	public CheckCountTask loadById(Long taskId) {
		return this.checkCountTaskDao.findOne(taskId);
	}

	/**
	 * 保存点数数据
	 * @param jsonArray
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveCountData(JSONArray countData,String countTaskCode) throws Exception {
	  try {
		    //保存点数数据
		    List<CheckPlanItem> itemList=new ArrayList<CheckPlanItem>();
			for (Object obj : countData) {
				@SuppressWarnings("unchecked")
				Map<String, String> map=(Map<String, String>) obj;
				Long itemId=Long.valueOf(map.get("id"));
				Integer salesNum_check=StringUtils.isBlank(map.get("salesNum"))?null:Integer.valueOf(map.get("salesNum"));
				Integer unusedNum_check=StringUtils.isBlank(map.get("unusedNum"))?null:Integer.valueOf(map.get("unusedNum"));
				Integer orderNum_check=StringUtils.isBlank(map.get("orderNum"))?null:Integer.valueOf(map.get("orderNum"));
				
				CheckPlanItem item=this.checkPlanItemDao.findOne(itemId);
				
				int salesNum=item.getSalesNum();
				int unusedNum=item.getUnusedNum();
				int orderNum=item.getOrderNum();
				
				
				//保存点数数据
				item.setSalesNumCheck(salesNum_check);
				item.setUnusedNumCheck(unusedNum_check);
				item.setOrderNumCheck(orderNum_check);
				
				//生成校对数据
				int salesNumFix=salesNum_check-salesNum;
				int unusedNumFix=unusedNum_check-unusedNum;
				int orderNumFix=orderNum_check-orderNum;
				item.setSalesNumFix(salesNumFix);
				item.setOrderNumFix(orderNumFix);
				item.setUnusedNumFix(unusedNumFix);
				
				//冲正标识
				if(salesNumFix!=0 || unusedNumFix!=0 || orderNumFix!=0){
					item.setReverseFlag("need");  //需要冲正
				}else{
					item.setReverseFlag("notneed");  //不需要冲正
				}
				
				itemList.add(item);
				
			}
			this.checkPlanItemDao.save(itemList);
			
			//保存任务状态为：点数中
			CheckCountTask countTask=this.checkCountTaskDao.loadByTaskCode(countTaskCode);
			countTask.setStatus("doing");
			this.checkCountTaskDao.save(countTask);
			
		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * 完成点数
	 * @param jsonArray
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void finishCountData(JSONArray countData,String countTaskCode) throws Exception {
		try {
			//保存点数数据
			this.saveCountData(countData,countTaskCode);
			
			//修改点数任务状态：完成
			CheckCountTask countTask=this.checkCountTaskDao.loadByTaskCode(countTaskCode);
			countTask.setStatus("finish");
			this.checkCountTaskDao.save(countTask);
			
			//修改计划状态：完成
			CheckPlan plan=this.checkPlanDao.loadByPlanCode(countTask.getPlanCode());
			plan.setStatus("3");
			this.checkPlanDao.save(plan);
			
			//创建校对任务
			CheckFixTask fixTask=new CheckFixTask();
			Date now=new Date();
			fixTask.setCreateTime(now);
			fixTask.setCustomerCode(countTask.getCustomerCode());
			fixTask.setPlanCode(countTask.getPlanCode());
			fixTask.setStatus("undo");
			fixTask.setTaskCode(TMSTransportRule.generateFixTaskCode());
			fixTask.setWarehouseCode(countTask.getWarehouseCode());
			this.checkFixTaskDao.save(fixTask);
			
			
			
		} catch (Exception e) {
			throw e;
		}
	}

}